<template>
  <view class="chat">
    <!-- 顶部标题 -->
    <view class="topTabbar">
      <!-- 返回图标 -->
      <u-icon class="icon" name="arrow-left" size="20px" color="#000" @click="goback()"></u-icon>
      <!-- 标题 -->
    </view>
    <scroll-view :style="{ height: `${windowHeight - inputHeight - 60}rpx` }" id="scrollview" scroll-y="true"
      :scroll-top="scrollTop" class="scroll-view">
      <!-- 聊天主体 -->
      <view id="msglistview" class="chat-body">
        <!-- 聊天记录 -->
        <view v-for="(item, index) in msgList" :key="index">
          <!-- 自己发的消息 -->
          <view class="item self" v-if="item.userContent != ''">
            <!-- 文字内容 -->
            <view class="content right">
              {{ item.userContent }}
            </view>
            <!-- 头像 -->
            <image class="avatar" :src="item.image">
            </image>
          </view>
          <!-- 机器人发的消息 -->
          <view  class="item Ai" v-if="item.botContent != ''">
            <!-- 头像 -->
            <image class="avatar" :src="item.image">
            </image>
            <!-- 文字内容 -->
            <view class="content left">
              <rich-text  :nodes="md.render(item.botContent)" ></rich-text>
            </view>
          </view>
        </view>
      </view>
    </scroll-view>
    <!-- 底部消息发送栏 -->
    <!-- 用来占位，防止聊天消息被发送框遮挡 -->
    <view class="chat-bottom sticky bottom-0" :style="{ height: `${inputHeight}rpx` }">
      <view class="send-msg" :style="{ bottom: `${keyboardHeight - 60}rpx` }">
        <view class="uni-textarea">
          <textarea v-model="chatMsg" confirm-type="send" @confirm="handleSend" placeholder="快来聊天吧~"
            :show-confirm-bar="false" :adjust-position="false" @linechange="sendHeight" @focus="focus" @blur="blur" :disabled="!currentUser"
            auto-height></textarea>
        </view>
        <tm-button @click="handleSend" class="send-btn" :disabled="!buttonIsEnable || !currentUser || !chatMsg">发送</tm-button>
      </view>
    </view>
  </view>
</template>
<script setup lang="ts">
import { ref, computed, getCurrentInstance } from 'vue';
import { onLoad } from '@dcloudio/uni-app';
import mpHtml from "mp-html/dist/uni-app/components/mp-html/mp-html";
import { marked } from "marked";
import highlight from "highlight.js";
import hljs from "highlight.js";
import "highlight.js/scss/atom-one-dark.scss";
import markdownIt from 'markdown-it';
// import {useTowxml} from '@/wxcomponents/towxml/index.js';

const instance = getCurrentInstance();
// const appContext = instance?.appContext
// const testData = appContext?.config.globalProperties.$towxml('``111``', 'markdown')

const mdOptions = (markdownIt.Options = {
  html:true,        // 在源码中启用 HTML 标签
  linkify: true,// 将类似 URL 的文本自动转换为链接。
  typographer: true,// 双 + 单引号替换对，当 typographer 启用时。
  breaks: true, // 转换段落里的 '\n' 到 <br>。
  langPrefix: "language-",
  // 代码高亮
  highlight(str, lang) {
    if (lang && highlight.getLanguage(lang)) {
      try {
        return (
          '<pre class="code"><code>' +
          highlight.highlight(lang, str, true).value +
          "</code></pre>"
        );
      } catch (__) {}
    }
    return "";
  },
});
let md:markdownIt = new markdownIt(mdOptions);
// 定义响应式数据
const keyboardHeight = ref(0);
const bottomHeight = ref(0);
const scrollTop = ref(0);
const userId = ref('');
const chatMsg = ref('');
const minWindowHeight = computed(() => {
  console.log(uni.getSystemInfoSync().windowHeight);

  return uni.getSystemInfoSync().windowHeight
})
const msgList = ref([
  {
    botContent: 'nihao ### 你好',
    userContent: "",
    image: "/static/logo.png"
  },
  {
    botContent: "",
    userContent: "你好呀，非常高兴认识你",
    image: "/static/logo.png"
  },

]);

// 计算属性
const windowHeight = computed(() => {
  return pxToRpx(uni.getSystemInfoSync().windowHeight);
});

const inputHeight = computed(() => {
  console.log("inputHeight", bottomHeight.value, keyboardHeight.value);

  return bottomHeight.value + keyboardHeight.value;
});

const currentUser = ref({})

const initHighLight = () =>{
      hljs.configure({
        useBR: true,
        tabReplace: " ",
      });
      marked.setOptions({
        renderer: new marked.Renderer(),
        gfm: true,
        tables: true,
        breaks: false,
        pedantic: false,
        highlight: function (code, lang) {
          if (lang && hljs.getLanguage(lang)) {
            return hljs.highlight(lang, code, true).value;
          } else {
            return hljs.highlightAuto(code).value;
          }
        },
      });
    }

// 生命周期钩子
onLoad(() => {
  initHighLight()
  uni.onKeyboardHeightChange((res) => {
    keyboardHeight.value = res.height;
    if (keyboardHeight.value < 0) keyboardHeight.value = 0;
  });
  console.log(windowHeight.value);
  currentUser.value = uni.getStorageSync('userinfo')
});

// onUnmounted(() => {
//   // uni.offKeyboardHeightChange();
// });

// 方法
const goback = () => {
  uni.switchTab({
    url: "/pages/tutorship/tutorship"
  });
};

const focus = () => {
  scrollToBottom();
};

const blur = () => {
  scrollToBottom();
};

// const rpxToPx = (px: number) => {
//   const { windowWidth } = uni.getSystemInfoSync();
//   const rpx = (750 / windowWidth) * px;
//   return Math.floor(rpx);
// };

const pxToRpx = (px: number) => {
  const { windowWidth } = uni.getSystemInfoSync();
  const rpx = (750 / windowWidth) * px;
  return Math.floor(rpx);
}

const sendHeight = () => {
  setTimeout(() => {
    const query = uni.createSelectorQuery();
    query.select('.send-msg').boundingClientRect();
    query.exec((res) => {
      console.log(res);
      bottomHeight.value = res[0].height;
    });
  }, 10);
};

const scrollToBottom = () => {
  setTimeout(() => {
    const query = uni.createSelectorQuery().in(instance);
    query.select('#scrollview').boundingClientRect();
    query.select('#msglistview').boundingClientRect();
    query.exec((res) => {
      console.log(res);

      if (res[1].height > res[0].height) {
        scrollTop.value = res[1].height - res[0].height;
      }
    });
  }, 15);
};

const showText = (text: string) => {

}

function decodeUnicode(str) {
  return str.replace(/\\u[\dA-Fa-f]{4}/g, function(match) {
    return String.fromCharCode(parseInt(match.substr(2), 16));
  });
}

const buttonIsEnable = ref(true)
const handleSend = () => {
  if (!chatMsg.value || !/^\s+$/.test(chatMsg.value)) {
    buttonIsEnable.value = false
    const obj = {
      botContent: "",
      userContent: chatMsg.value,
      image: "/static/logo.png"
    };
    msgList.value.push(obj);
    scrollToBottom();
    const requestTask = uni.request({
      url: 'http://localhost:18080/ai/chat',
      method: 'GET',
      responseType: 'text',
      enableChunked: true,  //流式输出需要设置enableChunked为true
      data: {
        message: chatMsg.value,
      },
      success: function (res) {
        console.log(JSON.stringify(res))
        buttonIsEnable.value = true
        // msgList.value[msgList.value.length - 1].botContent = md.render(msgList.value[msgList.value.length - 1].botContent);
      // msgList.value[msgList.value.length - 1].botContent = useTowxml(msgList.value[msgList.value.length - 1].botContent, 'markdown')
        console.log(msgList.value[msgList.value.length - 1].botContent);
        let newMsg = {
          botContent: ``,
          userContent: '',
          image: '/static/logo.png'
        }
        msgList.value.push(newMsg);
      },
      fail: function (err) {
      }
    });
    requestTask.onChunkReceived((res) => {
      // 流式输出，每次收到数据片段就进行处理
      const uint8Array = new Uint8Array(res.data);
      let text = String.fromCharCode.apply(null, uint8Array);
      // console.log("text", text);

      text = decodeURIComponent(escape(text));

      // text = text.replaceAll(/\r\n/g, '');
      text = text.replaceAll(/\n/g, '');
      // console.log(text);

      text = text.replaceAll("data:", "")
      text = decodeUnicode(text);
      // for (let index = 0; index < text.length; index++) {
      //   setTimeout(() =>newMsg.botContent += text[index],100)
      // }
      msgList.value[msgList.value.length - 1].botContent += text;
      
      scrollToBottom();
    })

    scrollToBottom();
    chatMsg.value = '';


  } else {
    uni.showToast('不能发送空白消息');
  }

  

};
</script>

<style lang="scss" scoped>
$chatContentbgc: #C2DCFF;
$sendBtnbgc: #4F7DF5;

view,
button,
text,
input,
textarea {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

/* 聊天消息 */
.chat {
  .topTabbar {
    width: 100%;
    display: flex;
    margin-top: 20rpx;
    justify-content: space-between;

    .icon {
      margin-left: 20rpx;
    }

    .text {
      margin: auto;
      font-size: 16px;
      font-weight: 700;
    }

    .button {
      width: 10%;
      margin: auto 20rpx auto 0rpx;
    }
  }

  .scroll-view {
    ::-webkit-scrollbar {
      display: none;
      width: 0 !important;
      height: 0 !important;
      -webkit-appearance: none;
      background: transparent;
      color: transparent;
    }

    // background-color: orange;
    background-color: #F6F6F6;

    .chat-body {
      display: flex;
      flex-direction: column;
      padding-top: 23rpx;
      // background-color:skyblue;

      .self {
        justify-content: flex-end;
      }

      .item {
        display: flex;
        padding: 23rpx 30rpx;
        // background-color: greenyellow;

        .right {
          background-color: $chatContentbgc;
        }

        .left {
          background-color: #FFFFFF;
        }

        // 聊天消息的三角形
        .right::after {
          position: absolute;
          display: inline-block;
          content: '';
          width: 0;
          height: 0;
          left: 100%;
          top: 10px;
          border: 12rpx solid transparent;
          border-left: 12rpx solid $chatContentbgc;
        }

        .left::after {
          position: absolute;
          display: inline-block;
          content: '';
          width: 0;
          height: 0;
          top: 10px;
          right: 100%;
          border: 12rpx solid transparent;
          border-right: 12rpx solid #FFFFFF;
        }

        .content {
          position: relative;
          max-width: 486rpx;
          border-radius: 8rpx;
          word-wrap: break-word;
          padding: 24rpx 24rpx;
          margin: 0 24rpx;
          border-radius: 5px;
          font-size: 32rpx;
          font-family: PingFang SC;
          font-weight: 500;
          color: #333333;
          line-height: 42rpx;
        }

        .avatar {
          display: flex;
          justify-content: center;
          width: 78rpx;
          height: 78rpx;
          background: $sendBtnbgc;
          border-radius: 50rpx;
          overflow: hidden;

          image {
            align-self: center;
          }

        }
      }
    }
  }

  /* 底部聊天发送栏 */
  .chat-bottom {
    width: 100%;
    height: 100rpx;
    background: #F4F5F7;
    transition: all 0.1s ease;

    .send-msg {
      display: flex;
      align-items: flex-end;
      padding: 16rpx 30rpx;
      width: 100%;
      min-height: 177rpx;
      position: fixed;
      bottom: 0;
      background: #fff;
      transition: all 0.1s ease;
    }

    .uni-textarea {
      padding-bottom: 70rpx;

      textarea {
        width: 537rpx;
        min-height: 75rpx;
        max-height: 500rpx;
        background: #f1f1f1;
        border-radius: 40rpx;
        font-size: 32rpx;
        font-family: PingFang SC;
        color: #333333;
        line-height: 74rpx;
        padding: 5rpx 8rpx;
        text-indent: 30rpx;
      }
    }

    .send-btn {
      display: flex;
      align-items: center;
      justify-content: center;
      margin-bottom: 76rpx;
      margin-left: 25rpx;
      width: 120rpx;
      height: 75rpx;
      border-radius: 50rpx;
      font-size: 28rpx;
      font-family: PingFang SC;
      font-weight: 500;
      line-height: 28rpx;
    }
  }
}
</style>